//
//  UserModel.m
//  EPLProject
//
//  Created by SDMac on 15/7/28.
//  Copyright (c) 2015年 Lim. All rights reserved.
//

#import "AutoArchiveModel.h"
#import <objc/runtime.h>
#import "CommonMacro.h"

@interface AutoArchiveModel ()

/** isEmpty 表示是否有数据，新增属性原plist文件要删除 */
@property (nonatomic, copy) NSString *isEmpty;

@end

@implementation AutoArchiveModel

#pragma mark - create singleton

static NSString * const HZLFileISEmpty = @"isEmpty";

static id _singleton = nil;

/**
 *  alloc方法内部会调用allocWithZone:
 *  zone : 系统分配给app的内存
 */
+ (id)allocWithZone:(struct _NSZone *)zone
{
    if (_singleton == nil)
    {
        static dispatch_once_t onceToken;
        
        dispatch_once(&onceToken,^{
            
            // 安全(这个代码只会被调用一次)
            _singleton = [super allocWithZone:zone];
            
        });
    }
    
    return _singleton;
}

- (id)init
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken,^{
        
        // 安全(这个代码只会被调用一次)
        _singleton = [super init];
        
    });
    
    return _singleton;
}

#pragma mark - public Methods

+ (instancetype)sharedInstance
{
    id model = [[self alloc] init];
    NSString *isEmpty = [model valueForKey:HZLFileISEmpty];
    
    if (!isEmpty)
    {
        NSFileManager *fileMgr = [NSFileManager defaultManager];
        
        if ([fileMgr fileExistsAtPath:[self filePath]] == YES)
        {
            model = [NSKeyedUnarchiver unarchiveObjectWithFile:[self filePath]];
            [model setValue:@"1" forKey:HZLFileISEmpty];
        }
    }
    
    return model;
}

+ (void)save:(id)model
{
    if ([NSKeyedArchiver archiveRootObject:model toFile:[self filePath]])
    {
        [model setValue:@"1" forKey:HZLFileISEmpty];
        DLog(@"路径:%@",[self filePath]);
    }
}

+ (void)deleteData
{
    id model = [[self alloc]init];
    
    [[[self class] allPropertyNames] enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        NSString *propertyKey = (NSString*)obj;
        
        if (propertyKey.length > 0)
        {
            [model setValue:nil forKey:propertyKey];
        }
    }];
    
    NSFileManager *fileMgr = [NSFileManager defaultManager];
    
    if ([fileMgr isDeletableFileAtPath:[self filePath]] == YES)
    {
        [fileMgr removeItemAtPath:[self filePath] error:nil];
    }
}

/**
 *  这个数组中的属性名将会被忽略：不进行归档
 */
+ (NSArray *)hzl_ignoredCodingPropertyNames
{
    return @[];
}

#pragma mark - private Methods

+ (NSString*)filePath
{
    NSString *fileName = [NSString stringWithFormat:@"%@.plist",[self class]];
    
    return [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:fileName];
}

+ (NSArray *)allPropertyNames
{
    // 存储所有的属性名称
    NSMutableArray *allNames = [[NSMutableArray alloc] init];
    [allNames addObject:HZLFileISEmpty];
    
    // 存储属性的个数
    unsigned int propertyCount = 0;
    
    // 通过运行时获取当前类的属性
    objc_property_t *propertys = class_copyPropertyList([self class], &propertyCount);
    
    // 把属性放到数组中
    for (int i = 0; i < propertyCount; i ++)
    {
        ///取出第一个属性
        objc_property_t property = propertys[i];
        
        const char * propertyName = property_getName(property);
        
        [allNames addObject:[NSString stringWithUTF8String:propertyName]];
    }
    
    // 去除不归档的属性
    [allNames removeObjectsInArray:[[self class] hzl_ignoredCodingPropertyNames]];
    
    // 释放
    free(propertys);
    
    return allNames;
}

#pragma mark - NSCoding 实现归档协议
/**
 *  归档
 */
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [[[self class] allPropertyNames] enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        NSString *propertyKey = (NSString*)obj;
        
        if (propertyKey.length > 0)
        {
            [aCoder encodeObject:[self valueForKey:propertyKey] forKey:propertyKey];
        }
    }];
}
/**
 *  解档
 */
- (id)initWithCoder:(NSCoder *)aCoder
{
    if (self = [super init])
    {
        [[[self class] allPropertyNames] enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            
            NSString *propertyKey = (NSString*)obj;
            
            if (propertyKey.length > 0)
            {
                [self setValue:[aCoder decodeObjectForKey:propertyKey] forKey:propertyKey];
            }
        }];
    }
    
    return self;
}

@end
